//
//  WDNetworkRequestObject.m
//  WDLogicBehind
//
//  Created by Alean on 2022/12/1.
//

#import "WDNetworkRequestObject.h"
#import "WDNetworkConfig.h"
//#import "WDURLProtocol.h"
#import "WDNetworkRequestModel.h"

#define kResponseDataFormatError    -10000
#define Network_error @"Network error -404"

@interface WDNetworkRequestObject ()

@property (nonatomic, weak) NSURLSessionTask *task;

@end

@implementation WDNetworkRequestObject

+ (AFHTTPSessionManager *)sharedSessionManager {
    static AFHTTPSessionManager *shared;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
//        configuration.protocolClasses = @[[WDURLProtocol class]];
        //接入 WDURLProtocol 后 HTTPMaximumConnectionsPerHost 设置 不生效
        configuration.HTTPMaximumConnectionsPerHost = 8;
        shared = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:configuration];
        // 修改请求格式为json
        shared.requestSerializer = [AFJSONRequestSerializer serializer];
        shared.requestSerializer.allowsCellularAccess = YES;
        shared.requestSerializer.timeoutInterval = [WDNetworkConfig sharedConfig].timeoutSeconds;
        shared.securityPolicy = [AFSecurityPolicy defaultPolicy];
        // 设置是否允许无效证书
        shared.securityPolicy.allowInvalidCertificates = YES;
        // 设置是否要验证域名
        shared.securityPolicy.validatesDomainName = NO;
        // 修改响应格式
        shared.responseSerializer = [AFJSONResponseSerializer serializer];
        shared.responseSerializer.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/xml", @"text/xml",@"text/html",@"text/json", @"application/json",@"text/plain",nil];
        // 待定
        shared.operationQueue.maxConcurrentOperationCount = 16;
    });
    return shared;
}

- (void)sendRequestWithPath:(NSString *)path
                     method:(RequestMethod)method
                 parameters:(NSDictionary *)parameters
                    success:(SuccessBlock)successBlock
                    failure:(FailureBlock)failuerBlock {
    NSAssert(self.task == nil, @"一个WDNetworkRequestObject 只能发送一个请求");
    // 在配置上检查base url
    NSString *fullUrl = [NSString stringWithFormat:@"%@%@",[WDNetworkConfig sharedConfig].baseUrl, path];
    NSString *methodString = [self getMethodString:method];
    
    // 添加相应的head文件
    [self addCustomHeaders];
    
    WDNetworkRequestModel *requestModel = [[WDNetworkRequestModel alloc] init];
    requestModel.requestUrl = fullUrl;
    requestModel.method = methodString;
    requestModel.successBlock = successBlock;
    requestModel.failureBlock = failuerBlock;

    // 拼接默认参数
    NSDictionary *fullParameters = [self appendDefaultParameters:parameters];
    requestModel.parameters = fullParameters;

    NSLog(@"API - %@ : %@", fullUrl, fullParameters);
    
    NSError * __autoreleasing requestSerializationError = nil;
    NSURLSessionDataTask *dataTask = [self dataTaskWithRequestModel:requestModel
                                                  requestSerializer:[WDNetworkRequestObject sharedSessionManager].requestSerializer
                                          constructingBodyWithBlock:nil
                                                              error:&requestSerializationError];
    self.task = dataTask;
    [dataTask resume];
}

- (void)sendPostRequestWithPath:(NSString *)path
                     paremeters:(NSDictionary *)parameters
      constructingBodyWithBlock:(void (^)(id<AFMultipartFormData> _Nonnull))block
                        success:(SuccessBlock)successBlock
                        failure:(FailureBlock)failuerBlock {
    NSAssert(self.task == nil, @"一个WDNetworkRequestObject 只能发送一个请求");
    NSString *fullUrl = path;
    NSString *methodString = @"POST";
    
    // 添加相应的head文件
    [self addCustomHeaders];
        
    WDNetworkRequestModel *requestModel = [[WDNetworkRequestModel alloc] init];
    requestModel.requestUrl = fullUrl;
    requestModel.method = methodString;
    requestModel.successBlock = successBlock;
    requestModel.failureBlock = failuerBlock;
    // 拼接默认参数
    NSDictionary *fullParameters = [self appendDefaultParameters:parameters];
    requestModel.parameters = fullParameters;
    
    NSError * __autoreleasing requestSerializationError = nil;
    NSURLSessionDataTask *dataTask = [self dataTaskWithRequestModel:requestModel
                                                  requestSerializer:[WDNetworkRequestObject sharedSessionManager].requestSerializer
                                          constructingBodyWithBlock:block
                                                              error:&requestSerializationError];
    self.task = dataTask;
    [dataTask resume];
}

- (NSURLSessionDataTask *)dataTaskWithRequestModel:(WDNetworkRequestModel *)requestModel
                                 requestSerializer:(AFHTTPRequestSerializer *)requestSerializer
                         constructingBodyWithBlock:(void (^)(id<AFMultipartFormData> _Nonnull))multipartFormBlock
                                             error:(NSError * __autoreleasing _Nullable *)error {
    NSMutableURLRequest *request;
    if (multipartFormBlock) {
        request = [requestSerializer multipartFormRequestWithMethod:requestModel.method
                                                          URLString:requestModel.requestUrl
                                                         parameters:requestModel.parameters
                                          constructingBodyWithBlock:multipartFormBlock
                                                              error:error];
    } else {
        request = [requestSerializer requestWithMethod:requestModel.method
                                             URLString:requestModel.requestUrl
                                            parameters:requestModel.parameters
                                                 error:error];
    }
    
    if (!request || *error) {
        NSLog(@"request error");
        return nil;
    }
    
   __block NSURLSessionDataTask *task =
    [[WDNetworkRequestObject sharedSessionManager] dataTaskWithRequest:request
                                                        uploadProgress:nil
                                                      downloadProgress:nil
                                                     completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
        NSLog(@"\nresponseObject = %@ \n %@", request.URL, responseObject);
        if (error) {
            NSString *msg = error.localizedFailureReason;
            requestModel.failureBlock(task, [NSError errorWithDomain:NSStringFromClass(WDNetworkRequestObject.class) code:error.code userInfo:@{NSLocalizedFailureReasonErrorKey:msg?:Network_error}], error.code);
        } else if (responseObject && [responseObject isKindOfClass:NSDictionary.class] && [[(NSDictionary *)responseObject allKeys] containsObject:@"code"]) {
            NSInteger code = [responseObject[@"code"] integerValue];
            NSString *msg = responseObject[@"message"];

            if (code == 0) {
//                NSString *string = [originData toJsonString];
//                NSString *replaceString = replaceSpecialUrlString(string);
//                NSDictionary *data = [replaceString zmkToDic];
                if ([NSJSONSerialization isValidJSONObject:responseObject]) {
                    NSError *parseError = nil;
                    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:responseObject options:NSJSONWritingPrettyPrinted error:&parseError];
                    NSString *string = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
                    if (parseError == nil) {
                        NSData *respcejsonData = [string dataUsingEncoding:NSUTF8StringEncoding];
                        NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:respcejsonData options:NSJSONReadingMutableContainers error:&parseError];
                        if (parseError == nil) {
                            NSLog(@"\nresponseObject 转换后 = %@ \n %@", request.URL, dic);
                            requestModel.successBlock(dic);
                        } else {
                            requestModel.successBlock(responseObject);
                        }
                    } else {
                        requestModel.successBlock(responseObject);
                    }
                } else {
                    requestModel.successBlock(responseObject);
                }
            } else {
                if (![WDNetworkConfig sharedConfig].customResponseCodeProcessBlock(code,msg)) {
                    requestModel.failureBlock(task, [NSError errorWithDomain:@"WDNetworkRequestObject_BizErr" code:code userInfo:@{NSLocalizedFailureReasonErrorKey:msg?:Network_error}], code);
                }
            }
        } else {
            requestModel.failureBlock(task, [NSError errorWithDomain:NSStringFromClass(WDNetworkRequestObject.class) code:kResponseDataFormatError userInfo:@{NSLocalizedFailureReasonErrorKey:Network_error}], kResponseDataFormatError);
        }
        
        [self printResponse:error responseObject:responseObject requestObject:requestModel];
    }];
    
    return task;
}

- (NSDictionary *)appendDefaultParameters:(NSDictionary *)parameters {
    NSMutableDictionary *dict = [WDNetworkConfig sharedConfig].defailtParameters.mutableCopy;
    if (dict) {
        [dict addEntriesFromDictionary:parameters];
        return dict.copy;
    }
    return parameters;
}

#pragma mark set headers
- (void)addCustomHeaders {
    NSDictionary *customHeaders = [WDNetworkConfig sharedConfig].customDict;
    if (customHeaders.allKeys.count > 0) {
        __weak typeof(self) weakSelf = self;
        [customHeaders enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            [[WDNetworkRequestObject sharedSessionManager].requestSerializer setValue:obj forHTTPHeaderField:key];
        }];
    }
}

- (NSString *)getMethodString:(RequestMethod)method {
    switch (method) {
        case RequestMethodGet:
            return @"GET";
        case RequestMethodPost:
            return @"POST";
        case RequestMethodPut:
            return @"PUT";
        case RequestMethodHead:
            return @"HEAD";
        default:
            return @"POST";
            break;
    }
}

- (void)cancel {
    if (self.task.state == NSURLSessionTaskStateRunning ||
        self.task.state == NSURLSessionTaskStateSuspended) {
        [self.task cancel];
    }
}
#pragma mark - Log
- (void)printResponse:(NSError * _Nullable)error
       responseObject:(id _Nullable)responseObject
        requestObject:(WDNetworkRequestModel *)requestModel {
    NSLog(@"[Network Log] request url : %@",requestModel.requestUrl);
    NSLog(@"[Network Log] request parameters : %@",requestModel.parameters);
    NSLog(@"[Network Log] request header : %@",[WDNetworkConfig sharedConfig].customDict);
    if (error) {
        NSLog(@"request url:%@ request parameters :%@ errorCode:%@ errorStr:%@", requestModel.requestUrl, requestModel.parameters, @(error.code).stringValue, error.localizedDescription?:@"");
    } else {
        NSLog(@"[Network Log] request response: %@", responseObject);
    }
}

@end
